/*****************************************************************************/
/* This is the program skeleton for homework 2 in CS 184 by Ravi Ramamoorthi */
/* Extends HW 1 to deal with shading, more transforms and multiple objects   */
/*****************************************************************************/

// This file is display.cpp.  It includes the skeleton for the display routine

// Basic includes to get this file to work.  
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <deque>
#include <stack>
#include <GL/glew.h>
#include <GL/glut.h>
#include "Transform.h"


using namespace std ; 
#include "GLObject.h"
#include "variables.h"
#include "readfile.h"

// New helper transformation function to transform vector by modelview 
// May be better done using newer glm functionality.
// Provided for your convenience.  Use is optional.  
// Some of you may want to use the more modern routines in readfile.cpp 
// that can also be used.  

void transformvec (const GLfloat input[4], GLfloat output[4]) {
  GLfloat modelview[16] ; // in column major order
  glGetFloatv(GL_MODELVIEW_MATRIX, modelview) ; 
  
  for (int i = 0 ; i < 4 ; i++) {
    output[i] = 0 ; 
    for (int j = 0 ; j < 4 ; j++) 
      output[i] += modelview[4*j+i] * input[j] ; 
  }
}

void display() {


	//render scene
	glClearColor(0, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        // I'm including the basic matrix setup for model view to 
        // give some sense of how this works.  
	
	mat4 mv ; 
	glMatrixMode(GL_PROJECTION);
        // I am changing the projection stuff to be consistent with lookat
		float aspect = w / (float) h, zNear = 0.1, zFar = 99.0 ;
        if (useGlu) mv = glm::perspective(fovy,aspect,zNear,zFar) ; 
        else {
          mv = Transform::perspective(fovy,aspect,zNear,zFar) ; 
          mv = glm::transpose(mv) ; // accounting for row major 
        }
        glLoadMatrixf(&mv[0][0]) ; 

	glViewport(0, 0, w, h);

	glMatrixMode(GL_MODELVIEW);
	
    if (useGlu) mv = glm::lookAt(eye,center,up) ; 
	else {
		mv = Transform::lookAt(eye,center,up) ; 
        mv = glm::transpose(mv) ; // accounting for row major
    }
    glLoadMatrixf(&mv[0][0]) ; 

    // Set Light and Material properties for the teapot
    // Lights are transformed by current modelview matrix. 
    // The shader can't do this globally. 
    // So we need to do so manually.  
    if (numused) {
        glUniform1i(enablelighting,true) ;

        // YOUR CODE FOR HW 2 HERE.  
        // You need to pass the lights to the shader. 
        // Remember that lights are transformed by modelview first.
		float light_pos[4*numLights];
		for( int i = 0; i< 4*numused ; i+=4){
			//printf("lightposn[%d].w=%.3f,%.3f,%.3f,%.3f\n", i,lightposn[i],lightposn[i+1],lightposn[i+2], lightposn[i+3]);
			transformvec( &lightposn[i], &light_pos[i]);//transform light by modelview
			//printf("*light_pos[%d].w=%.3f,%.3f,%.3f,%.3f\n", i,light_pos[i],light_pos[i+1],light_pos[i+2], light_pos[i+3]);
		}
		glUniform1i(numusedcol, numused);
		glUniform4fv(lightpos, numused, light_pos);
		glUniform4fv(lightcol, numused, lightcolor);
    }
    else glUniform1i(enablelighting,false) ; 
     

    // Transformations for objects, involving translation and scaling 
    mat4 sc=mat4(1.0) , tr=mat4(1.0), transf=mat4(1.0) ; 
    sc = Transform::scale(sx,sy,1.0) ; 
    tr = Transform::translate(tx,ty,0.0); 
		
	transf = (sc)*(tr)*Transform::lookAt(eye,center,up) ;
    // YOUR CODE FOR HW 2 HERE.  
    // You need to use scale, translate and modelview to 
    // set up the net transformation matrix for the objects.  
    // Account for GLM issues etc.  

	mat4 matx;
	glUniform4fv(ambientcol ,1, starambient);
	glUniform4fv(diffusecol ,1, stardiffuse );
	glUniform4fv(specularcol ,1, starspecular );
	glUniform4fv( emissioncol ,1, staremission);
	glUniform1f(shininesscol, starshininess);
	mat4 rot = (mat4(Transform::rotate( ((float)(animate))*.036, vec3(0,0,1))));
	for (int i=0;i<numstars; i++){
		//find direction, make translate matrix
		glLoadIdentity();
		matx = Transform::translate(stars[i].x,stars[i].y,stars[i].z)*rot;
		matx = glm::transpose((matx)*(transf));
		glLoadMatrixf(&matx[0][0]);
		drawcolor(CUBE, 0) ; 
		//glutSolidSphere(.05, 20, 20);
	}



	for (int i = 0 ; i < GLObject::objects->size() ; i++) {
        GLObject * obj = ((*GLObject::objects)[i]) ; 
		obj->draw(transf);
    }
    
    glutSwapBuffers();
}
